home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 003 / _gs / !GS / c / ZFILE < prev    next >
Text File  |  1991-10-27  |  16KB  |  587 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* zfile.c */
  21. /* Non-I/O file operators for Ghostscript */
  22. #include "memory_.h"
  23. #include "string_.h"
  24. #include "ghost.h"
  25. #include "gp.h"
  26. #include "errors.h"
  27. #include "oper.h"
  28. #include "alloc.h"
  29. #include "estack.h"            /* for filenameforall */
  30. #include "iutil.h"
  31. #include "save.h"            /* for restore */
  32. #include "stream.h"
  33. #include "file.h"            /* must come after stream.h */
  34. #include "store.h"
  35.  
  36. /* Forward references */
  37. int lib_file_open(P3(byte *, uint, ref *));
  38. int file_open(P5(byte *, uint, char *, ref *, stream **));
  39. int file_close(P2(ref *, stream *));
  40. private int open_std_file(P3(os_ptr, char *, os_ptr));
  41. /* In zfileio.c */
  42. ref *zget_current_file(P0());
  43.  
  44. /* Imported from gs.c */
  45. extern char **gs_lib_paths;        /* search path list, */
  46.                     /* terminated by a null pointer */
  47.  
  48. /* The chain of all open files.  We need this only */
  49. /* so that we can do the right thing for restore (and GC someday). */
  50. private ref all_files;            /* t_file */
  51. #define file_list all_files.value.pfile
  52.  
  53. /* File buffer sizes.  For real files, this is arbitrary, */
  54. /* since the C library does its own buffering in addition. */
  55. /* stdout and stderr use smaller buffers, */
  56. /* on the assumption that they are usually not real files. */
  57. /* The buffer size for type 1 encrypted files is NOT arbitrary: */
  58. /* it must be at most 512. */
  59. #define buffer_size 512
  60.  
  61. /* Standard file objects: */
  62. /* 0 is stdin, 1 is stdout, 2 is stderr, 3 is lineedit, 4 is statementedit */
  63. #define num_std_files 5
  64. stream invalid_file_entry;
  65. private byte
  66. #define stdin_buf_size 1
  67.     stdin_buf[stdin_buf_size],
  68. #define stdout_buf_size 128
  69.     stdout_buf[stdout_buf_size],
  70. #define stderr_buf_size 128
  71.     stderr_buf[stderr_buf_size],
  72. #define lineedit_buf_size 160
  73.     lineedit_buf[lineedit_buf_size];
  74. /* statementedit is equivalent to lineedit for now */
  75. stream std_files[num_std_files];
  76. private char *std_file_names[num_std_files] =
  77.    {    "%stdin",
  78.     "%stdout",
  79.     "%stderr",
  80.     "%lineedit",
  81.     "%statementedit"
  82.    };
  83. private int std_file_attrs[num_std_files] =
  84.    {    a_read+a_execute,
  85.     a_write+a_execute,
  86.     a_write+a_execute,
  87.     a_read+a_execute,
  88.     a_read+a_execute
  89.    };
  90.  
  91. #ifdef ARC
  92. /* On the Archimedes, we often want to replace files with names like x.y.z by
  93.    x.z.y. This function checks to see whether a file has one or a range of standard
  94.    extensions (z), and makes the change. The result is placed in a given buffer.
  95.  
  96.    The typedef gives us a suitable temporary buffer.
  97. */
  98.  
  99. #define ARC_MAX_FILE_NAME 4096  /* A likely value */
  100. typedef char arc_buf[ARC_MAX_FILE_NAME];
  101.  
  102. private struct arc_ext
  103. {
  104.     char *ext;
  105.     int  len;
  106. } arc_extension[] =
  107. {   /* Shortest must be first */
  108.     "ps",  2,
  109.     "gsf", 3,
  110.     "",    0
  111. };
  112.  
  113.  
  114. /* Change and copy name. To and from must not overlap. */
  115. private void arc_cvt_name(char *to, char *from, int len)
  116. {
  117.     struct arc_ext *ext;
  118.     int    elen;
  119.  
  120.     to[len] = 0;
  121.  
  122.     for (ext = arc_extension ; (elen = ext->len) != 0 ; ext++)
  123.     {
  124.         if (from[len-elen-1] == '.' && memcmp(ext->ext, from+len-elen, elen) == 0)
  125.         {
  126.             /* Look back for earlier '.' */
  127.             int i;
  128.             for (i = len-elen-2 ; i >= 0 ; i--)
  129.             {
  130.                 if (from[i] == '.')
  131.                 {
  132.                      /* Copy up to and including "." */
  133.                      memcpy(to, from, i+1);
  134.                      break;
  135.                  }
  136.             }
  137.  
  138.             /* Add "ext." */
  139.             i += 1;
  140.             memcpy(to+i, ext->ext, elen);
  141.             to[i+elen] = '.';
  142.  
  143.             /* Copy chunk to go after "ext." */
  144.             elen += 1;
  145.             memcpy(to+i+elen, from+i, len-i-elen);
  146.  
  147.             return;
  148.         }
  149.     }
  150.  
  151.     /* No extension matches - simple copy */
  152.     memcpy(to, from, len);
  153.  
  154. }
  155. #endif
  156.  
  157. /* Initialize the file table */
  158. private void
  159. zfile_init()
  160. {    /* Create files for stdin, stdout, and stderr. */
  161.     /****** stdin IS NOT IMPLEMENTED PROPERLY ******/
  162.     sread_file(&std_files[0], stdin, stdin_buf, stdin_buf_size);
  163.     std_files[0].can_close = 0;
  164.     swrite_file(&std_files[1], stdout, stdout_buf, stdout_buf_size);
  165.     std_files[1].can_close = 0;
  166.     swrite_file(&std_files[2], stderr, stderr_buf, stderr_buf_size);
  167.     std_files[2].can_close = 0;
  168.     make_tav(&all_files, t_file, 0, pfile, (stream *)0);
  169.     s_disable(&invalid_file_entry);
  170. }
  171.  
  172. /* file */
  173. int
  174. zfile(register os_ptr op)
  175. {    char *file_access;
  176.     ref fname;
  177.     int code;
  178.     stream *s;
  179.     fname = op[-1];
  180.     check_type(fname, t_string);
  181.     check_type(*op, t_string);
  182.     if ( r_size(op) != 1 ) return e_invalidfileaccess;
  183.     switch ( *op->value.bytes )
  184.        {
  185.     case 'r': file_access = "r"; break;
  186.     case 'w': file_access = "w"; break;
  187.     default: return e_invalidfileaccess;
  188.        }
  189.     code = open_std_file(op - 1, file_access, op - 1);
  190.     switch ( code )
  191.        {
  192.     case 0:                /* successful open */
  193.         pop(1);
  194.     default:            /* unsuccessful open */
  195.         return code;
  196.     case e_undefinedfilename:    /* not a %file */
  197.         ;
  198.        }
  199.     code = file_open(fname.value.bytes, r_size(&fname),
  200.              file_access, op - 1, &s);
  201.     if ( code >= 0 ) pop(1);
  202.     return code;
  203. }
  204.  
  205. /* closefile */
  206. int
  207. zclosefile(register os_ptr op)
  208. {    stream *s;
  209.     int code;
  210.     check_file(s, op);
  211.     if ( s->can_close == 0 )
  212.         return e_invalidaccess;    /* can't close std file */
  213.     if ( (code = file_close(op, s)) >= 0 )
  214.        {    /* If we just closed the file from which the interpreter */
  215.         /* is reading, zap it on the exec stack. */
  216.         ref *fp = zget_current_file();
  217.         if ( fp != 0 && fptr(fp) == fptr(op) )
  218.             /* A null would confuse the estack parser.... */
  219.             make_tasv(fp, t_array, a_executable+a_execute, 0, refs, (ref *)0);
  220.         pop(1);
  221.        }
  222.     return code;
  223. }
  224.  
  225. /* ------ Level 2 extensions ------ */
  226.  
  227. /* deletefile */
  228. int
  229. zdeletefile(register os_ptr op)
  230. {    char *str;
  231.     int stat;
  232.     check_read_type(*op, t_string);
  233.     str = ref_to_string(op, "deletefile");
  234.     if ( str == 0 ) return e_VMerror;
  235. #ifdef ARC
  236.     {
  237.         arc_buf temp_name;
  238.         arc_cvt_name(temp_name, str, strlen(str));
  239.         stat = remove(temp_name);
  240.     }
  241. #else
  242.     stat = unlink(str);
  243. #endif
  244.     alloc_free(str, r_size(op) + 1, 1, "deletefile");
  245.     if ( stat != 0 ) return e_ioerror;
  246.     pop(1);
  247.     return 0;
  248. }
  249.  
  250. /* filenameforall */
  251. private int file_continue(P1(os_ptr));
  252. int
  253. zfilenameforall(register os_ptr op)
  254. {    file_enum *pfen;
  255.     check_write_type(*op, t_string);
  256.     check_proc(op[-1]);
  257.     check_read_type(op[-2], t_string);
  258.     /* Push a mark, the pattern, the scratch string, the enumerator, */
  259.     /* and the procedure, and invoke the continuation. */
  260.     check_estack(7);
  261.     pfen = gp_enumerate_files_init((char *)op[-2].value.bytes, r_size(op - 2), alloc, alloc_free);
  262.     if ( pfen == 0 ) return e_VMerror;
  263.     mark_estack(es_for);
  264.     *++esp = op[-2];
  265.     *++esp = *op;
  266.     ++esp;
  267.     make_tasv(esp, t_string, a_read+a_execute+a_executable, 0,
  268.           bytes, (byte *)pfen);
  269.     *++esp = op[-1];
  270.     pop(3);  op -= 3;
  271.     return file_continue(op);
  272. }
  273. /* Continuation operator for enumerating files */
  274. private int
  275. file_continue(register os_ptr op)
  276. {    es_ptr pscratch = esp - 2;
  277.     file_enum *pfen = (file_enum *)esp[-1].value.bytes;
  278.     uint len = r_size(pscratch);
  279.     uint code = gp_enumerate_files_next(pfen, (char *)pscratch->value.bytes, len);
  280.     if ( code == ~(uint)0 )        /* all done */
  281.        {    gp_enumerate_files_close(pfen);
  282.         esp -= 4;        /* pop mark, scatch, pfen, proc */
  283.        }
  284.     else if ( code > len )        /* overran string */
  285.        {    gp_enumerate_files_close(pfen);
  286.         return e_rangecheck;
  287.        }
  288.     else if ( !string_match(pscratch->value.bytes, code,
  289.                 pscratch[-1].value.bytes, r_size(&pscratch[-1]))
  290.         )
  291.        {    /* Enumerator was too liberal, ignore this one. */
  292.         push_op_estack(file_continue);    /* come again */
  293.        }
  294.     else
  295.        {    push(1);
  296.         ref_assign(op, pscratch);
  297.         r_set_subrange_size(op, code);
  298.         push_op_estack(file_continue);    /* come again */
  299.         *++esp = pscratch[2];    /* proc */
  300.        }
  301.     return o_check_estack;
  302. }
  303.  
  304. /* renamefile */
  305. int
  306. zrenamefile(register os_ptr op)
  307. {    char *str1 = 0, *str2 = 0;
  308.     check_read_type(*op, t_string);
  309.     check_read_type(op[-1], t_string);
  310.     str1 = ref_to_string(op - 1, "renamefile(from)");
  311. #ifdef ARC
  312.     if ( str1 != 0 && str2 != 0 )
  313.     {
  314.         arc_buf temp1, temp2;
  315.         arc_cvt_name(temp1, str1, strlen(str1));
  316.         arc_cvt_name(temp2, str2, strlen(str2));
  317.         if ( rename(temp1, temp2) )
  318.         {    pop(2);
  319.         }
  320.     }
  321. #else
  322.     str2 = ref_to_string(op, "renamefile(to)");
  323.     if ( str1 != 0 && str2 != 0 && rename(str1, str2) == 0 )
  324.        {    pop(2);
  325.        }
  326. #endif
  327.     if ( str1 != 0 )
  328.         alloc_free(str1, r_size(op - 1) + 1, 1, "renamefile(from)");
  329.     if ( str2 != 0 )
  330.         alloc_free(str2, r_size(op) + 1, 1, "renamefile(to)");
  331.     return 0;
  332. }    
  333.  
  334. /* ------ Ghostscript extensions ------ */
  335.  
  336. /* findlibfile */
  337. int
  338. zfindlibfile(register os_ptr op)
  339. {    int code;
  340.     check_type(*op, t_string);
  341.     code = open_std_file(op, "r", op - 1);
  342.     switch ( code )
  343.        {
  344.     case 0:                /* successful open */
  345.         push(1);
  346.         make_bool(op, 1);
  347.     default:            /* unsuccessful open */
  348.         return code;
  349.     case e_undefinedfilename:    /* not a %file */
  350.         ;
  351.        }
  352.     code = lib_file_open(op->value.bytes, r_size(op), op);
  353.     push(1);
  354.     make_bool(op, code >= 0);
  355.     return 0;
  356. }
  357.  
  358. /* type1decryptfile */
  359. int
  360. ztype1decryptfile(register os_ptr op)
  361. {    stream *s;
  362.     ushort state;
  363.     ref dec_file;
  364.     int code;
  365.     stream *es;
  366.     check_type(op[-1], t_integer);
  367.     state = op[-1].value.intval;
  368.     if ( op[-1].value.intval != state )
  369.         return e_rangecheck;    /* state value was truncated */
  370.     check_read_file(s, op);
  371.     code = file_open((byte *)0, 0, "r", &dec_file, &es);
  372.     if ( code < 0 ) return code;
  373.     sread_decrypt(es, fptr(op), es->cbuf, es->bsize, state);
  374.     op[-1] = dec_file;
  375.     pop(1);
  376.     return 0;
  377. }
  378.  
  379. /* ------ Initialization procedure ------ */
  380.  
  381. op_def zfile_op_defs[] = {
  382.     {"1closefile", zclosefile},
  383.     {"1deletefile", zdeletefile},
  384.     {"2file", zfile},
  385.     {"3filenameforall", zfilenameforall},
  386.     {"1findlibfile", zfindlibfile},
  387.     {"2renamefile", zrenamefile},
  388.     {"2type1decryptfile", ztype1decryptfile},
  389.     op_def_end(zfile_init)
  390. };
  391.  
  392. /* ------ Non-operator routines ------ */
  393.  
  394. /* Open a file, using the search paths if necessary. */
  395. /* The startup code calls this to open the initialization file ghost.ps, */
  396. /* and any other files specified on the command line. */
  397. int
  398. lib_file_open(byte *fname, uint len, ref *pfile)
  399. {    int code;
  400.     char **ppath;
  401. #define max_len 200
  402.     char cname[max_len];
  403.     stream *s;
  404.     code = file_open(fname, len, "r", pfile, &s);
  405.     if ( code >= 0 ) return code;
  406.     if ( gp_file_name_is_absolute((char *)fname, len) )
  407.         return e_undefinedfilename;
  408.     /* Go through the list of search paths */
  409.     for ( ppath = gs_lib_paths; *ppath != 0; ppath++ )
  410.        {    char *path = *ppath;
  411.         for ( ; ; )
  412.            {    /* Find the end of the next path */
  413.             char *npath = path;
  414.             uint plen;
  415.             char *cstr;
  416.             uint clen;
  417.             while ( *npath != 0 && *npath != gp_file_name_list_separator )
  418.                 npath++;
  419.             plen = npath - path;
  420.             cstr = gp_file_name_concat_string(path, plen,
  421.                               (char *)fname, len);
  422.             /* Concatenate the prefix, combiner, and file name. */
  423.             clen = plen + strlen(cstr) + len;
  424.             if ( clen <= max_len )    /* otherwise punt */
  425.                {    memcpy(cname, path, plen);
  426.                 strcpy(cname + plen, cstr);
  427.                 memcpy(cname + clen - len, fname, len);
  428.                 code = file_open((byte *)cname, clen, "r",
  429.                          pfile, &s);
  430.                 if ( code >= 0 ) return code;
  431.                }
  432.             /****** NYI ******/
  433.             if ( !*npath ) break;
  434.             path = npath + 1;
  435.            }
  436.        }
  437.     return code;
  438. }
  439.  
  440. /* Open a file and create a file object. */
  441. /* Return 0 if successful, error code if not. */
  442. /* If fname==0, set up the file entry, stream, and buffer, */
  443. /* but don't open an OS file or initialize the stream. */
  444. /* The filter routines also use this. */
  445. int
  446. file_open(byte *fname, uint len, char *file_access, ref *pfile, stream **ps)
  447. {    byte *buffer;
  448.     stream *s;
  449.     int code;
  450.     if ( len >= buffer_size )
  451.         return e_limitcheck;    /* we copy the file name into the buffer */
  452.     /* Allocate the stream first, since it persists */
  453.     /* even after the file has been closed. */
  454.     s = (stream *)alloc(1, sizeof(stream), "file_open(stream)");
  455.     if ( s == 0 ) return e_VMerror;
  456.     /* Allocate the buffer. */
  457.     buffer = (byte *)alloc(buffer_size, 1, "file_open(buffer)");
  458.     if ( buffer == 0 )
  459.        {    alloc_free((char *)s, 1, sizeof(stream), "file_open(stream)");
  460.         return e_VMerror;
  461.        }
  462.     if ( fname != 0 )
  463.        {    /* Copy the name (so we can terminate it with a zero byte.) */
  464.         char *file_name = (char *)buffer;
  465.         FILE *file;
  466.         memcpy(file_name, fname, len);
  467.         file_name[len] = 0;        /* terminate string */
  468.         /* Open the file. */
  469. #ifdef ARC
  470.         {
  471.             arc_buf temp_name;
  472.             arc_cvt_name(temp_name, file_name, len);
  473.             file = fopen(temp_name, file_access);
  474.         }
  475. #else
  476.         file = fopen(file_name, file_access);
  477. #endif
  478.         code = e_undefinedfilename;
  479.         if ( file == 0 )
  480.            {    alloc_free((char *)buffer, buffer_size, 1, "file_open(buffer)");
  481.             alloc_free((char *)s, 1, sizeof(stream), "file_open(stream)");
  482.             return code;
  483.            }
  484.         /* Set up the stream. */
  485.         if ( *file_access == 'r' )    /* reading */
  486.             sread_file(s, file, buffer, buffer_size);
  487.         else
  488.             swrite_file(s, file, buffer, buffer_size);
  489.        }
  490.     else                /* save the buffer and size */
  491.        {    s->cbuf = buffer;
  492.         s->bsize = buffer_size;
  493.        }
  494.     s->can_close = 1;
  495.     if ( file_list != 0 )
  496.         file_list->prev = s;
  497.     s->next = file_list;
  498.     s->prev = 0;
  499.     file_list = s;
  500.     make_file(pfile,
  501.         (*file_access == 'r' ? a_read+a_execute : a_write+a_execute),
  502.         s);
  503.     *ps = s;
  504.     return 0;
  505. }
  506.  
  507. /* Close a file.  The interpreter calls this when */
  508. /* it reaches the end of an executable file. */
  509. int
  510. file_close(ref *fp /* t_file */, stream *s)
  511. {    byte *buffer = s->cbuf;
  512.     switch ( s->can_close )
  513.        {
  514.     case 0:                /* can't close std files, ignore */
  515.         break;
  516.     case -1:            /* ignore on statement/lineedit */
  517.         sclose(s);
  518.         break;
  519.     default:            /* ordinary or filter file */
  520.         if ( sclose(s) ) return e_ioerror;
  521.         /* Free the stream and buffer in the reverse of the order */
  522.         /* in which they were created, and hope for LIFO storage behavior. */
  523.         alloc_free((char *)buffer, buffer_size, 1, "file_close(buffer)");
  524.         alloc_free((char *)s, 1, sizeof(stream), "file_close(stream)");
  525.         /* Unlink the file from the list of all files. */
  526.         if ( s->prev != 0 ) s->prev->next = s->next;
  527.         else file_list = s->next;
  528.         if ( s->next != 0 ) s->next->prev = s->prev;
  529.        }
  530.     s_disable(s);
  531.     return 0;
  532. }
  533.  
  534. /* ------ Internal routines ------ */
  535.  
  536. /* If a file name refers to one of the standard %files, */
  537. /* 'open' the file and return 0 or an error code, otherwise */
  538. /* return e_undefinedfilename. */
  539. private int
  540. open_std_file(os_ptr pfname, char *file_access, os_ptr pfile)
  541. {    int i;
  542.     for ( i = 0; i < num_std_files; i++ )
  543.       if ( !bytes_compare(pfname->value.bytes, r_size(pfname),
  544.                   (byte *)std_file_names[i],
  545.                   strlen(std_file_names[i]))
  546.         )
  547.        {    /* This is a standard file */
  548.         int attrs = (*file_access == 'r' ? a_read+a_execute : a_write+a_execute);
  549.         stream *s = &std_files[i];
  550.         if ( attrs != std_file_attrs[i] )
  551.             return e_invalidaccess;
  552.         make_file(pfile, attrs, s);
  553.         /* If this is %lineedit or %statementedit, */
  554.         /* read a line now. */
  555.         switch ( i )
  556.            {
  557.         case 3: case 4:
  558.            {    uint count;
  559.             int code = zreadline_stdin(lineedit_buf,
  560.                 lineedit_buf_size, &count);
  561.             if ( code < 0 ) return code;
  562.             sread_string(s, lineedit_buf, count);
  563.             s->can_close = -1;
  564.             return 0;
  565.            }
  566.            }
  567.         return 0;
  568.        }
  569.     return e_undefinedfilename;
  570. }
  571.  
  572. /* Close inaccessible files just before a restore. */
  573. void
  574. file_restore(alloc_save *save)
  575. {    while ( file_list != 0 &&
  576.         alloc_is_since_save((char *)file_list, save)
  577.           )
  578.        {    stream *s = file_list;
  579.         if ( s->can_close > 0 )    /* ignore std & buffered files */
  580.            {    sclose(s);
  581.            }
  582.         file_list = s->next;
  583.         if ( s->next != 0 ) s->next->prev = s->prev;
  584.         s_disable(s);
  585.        }
  586. }
  587.